package com.unitd.base.frame.plugin.db.datasource.factory;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Maps;
import com.unitd.base.frame.plugin.db.datasource.context.DataSourceContext;
import com.unitd.base.frame.plugin.db.datasource.properties.DruidProperties;
import com.unitd.base.frame.plugin.db.datasource.sqls.AddDatabaseInfoSql;
import com.unitd.base.frame.plugin.db.datasource.sqls.DatabaseListSql;
import com.unitd.base.frame.plugin.db.datasource.sqls.DeleteDatabaseInfoSql;
import com.unitd.base.frame.plugin.db.enums.DataSourceErrorEnum;
import com.unitd.base.frame.plugin.db.exception.DataSourceException;
import com.unitd.base.module.comm.enums.DeleteFlagEnum;
import com.unitd.base.module.comm.enums.StatusEnum;
import lombok.extern.slf4j.Slf4j;

import java.sql.*;
import java.util.Date;
import java.util.Map;

/**
 * 服务启动,初始化得到配置的数据源信息
 *
 * @author Hudan
 * @version 1.0
 * @filename DataSourceFactory.java
 * @copyright www.unitd.com
 * @date 2020-06-28
 */
@Slf4j
public class DataSourceFactory {

    /**
     * Druid数据库连接池连接配置参数对象
     */
    private DruidProperties druidProperties;

    public DataSourceFactory(DruidProperties druidProperties) {
        this.druidProperties = druidProperties;
    }

    /**
     * 查询所有数据源列表
     *
     * @return 数据源列表
     */
    public Map<String, DruidProperties> getAllDataBaseInfo() {

        Map<String, DruidProperties> dataSourceList = Maps.newHashMap();

        try {
            Class.forName(druidProperties.getDriverClassName());
            Connection conn = DriverManager.getConnection(
                    druidProperties.getUrl(), druidProperties.getUsername(), druidProperties.getPassword());

            PreparedStatement preparedStatement = conn.prepareStatement(new DatabaseListSql().getSql(druidProperties.getUrl()));
            ResultSet resultSet = preparedStatement.executeQuery();

            while (resultSet.next()) {
                DruidProperties druidProperties = createDruidProperties(resultSet);
                String dbName = resultSet.getString("db_name");
                dataSourceList.put(dbName, druidProperties);
            }

            return dataSourceList;
        } catch (Exception ex) {
            throw new DataSourceException(DataSourceErrorEnum.QUERY_DATASOURCE_INFO_ERROR);
        }
    }

    /**
     * 初始化master的数据源，要和properties配置的数据源一致
     */
    public void createMasterDatabaseInfo() {
        try {
            Class.forName(druidProperties.getDriverClassName());
            Connection conn = DriverManager.getConnection(
                    druidProperties.getUrl(), druidProperties.getUsername(), druidProperties.getPassword());

            PreparedStatement preparedStatement = conn.prepareStatement(new AddDatabaseInfoSql().getSql(druidProperties.getUrl()));

            // 对应的sys_datasource 表中的主键ID, 由于主库只有一个,故这里固定死为主库的ID从1开始
            preparedStatement.setLong(1, 1L);
            preparedStatement.setString(2, DataSourceContext.MASTER_DATASOURCE_TYPE);
            preparedStatement.setString(3, DataSourceContext.MASTER_DATASOURCE_NAME);
            preparedStatement.setString(4, druidProperties.getDriverClassName());
            preparedStatement.setString(5, druidProperties.getUrl());
            preparedStatement.setString(6, druidProperties.getUsername());
            preparedStatement.setString(7, druidProperties.getPassword());
            preparedStatement.setString(8, StatusEnum.ONE.getCode());
            preparedStatement.setString(9, DeleteFlagEnum.NO.getCode());
            preparedStatement.setString(10, DateUtil.formatDateTime(new Date()));
            preparedStatement.setString(11, DateUtil.formatDateTime(new Date()));
            preparedStatement.setString(12, "主数据源，项目启动数据源！");

            int i = preparedStatement.executeUpdate();
            log.info("初始化master的databaseInfo信息！初始化" + i + "条！");
        } catch (Exception ex) {
            log.error("初始化master的databaseInfo信息错误！", ex);
            throw new DataSourceException(DataSourceErrorEnum.QUERY_DATASOURCE_INFO_ERROR);
        }
    }

    /**
     * 删除master的数据源信息
     */
    public void deleteMasterDatabaseInfo() {
        try {
            Class.forName(druidProperties.getDriverClassName());
            Connection conn = DriverManager.getConnection(
                    druidProperties.getUrl(), druidProperties.getUsername(), druidProperties.getPassword());

            PreparedStatement preparedStatement = conn.prepareStatement(new DeleteDatabaseInfoSql().getSql(druidProperties.getUrl()));
            preparedStatement.setString(1, DataSourceContext.MASTER_DATASOURCE_NAME);
            int i = preparedStatement.executeUpdate();
            log.info("删除master的databaseInfo信息！删除" + i + "条！");
        } catch (Exception ex) {
            log.info("删除master的databaseInfo信息失败！", ex);
            throw new DataSourceException(DataSourceErrorEnum.QUERY_DATASOURCE_INFO_ERROR);
        }
    }

    /**
     * 通过查询结果组装druidProperties
     *
     * @param resultSet 查询结果集
     * @return
     */
    private DruidProperties createDruidProperties(ResultSet resultSet) {

        DruidProperties druidProperties = new DruidProperties();

        druidProperties.setTestOnBorrow(true);
        druidProperties.setTestOnReturn(true);

        try {
            druidProperties.setDriverClassName(resultSet.getString("jdbc_driver"));
            druidProperties.setUrl(resultSet.getString("jdbc_url"));
            druidProperties.setUsername(resultSet.getString("user_name"));
            druidProperties.setPassword(resultSet.getString("password"));
        } catch (SQLException e) {
            throw new DataSourceException(DataSourceErrorEnum.QUERY_DATASOURCE_INFO_ERROR);
        }

        return druidProperties;
    }
}